<?php
	/**
	 * XHTML helper class. Used for xHTML compatible tags generation
	 * 
	 * @package Helpers
	 * @author Perkin Anton
	 * @version 1.0
	 */ 
	class XHTML extends GlobalHelper
	{
		/**
		 * Meta tag buffer
		 * @var array
		 */
		static $meta_tag_buffer = array();
		
		/**
		 * CSS tag buffer
		 * @var array
		 */
		static $css_tag_buffer = array();
		
		/**
		 * JS tag buffer
		 * @var array
		 */
		static $js_tag_buffer = array();
		
		/**
		 * default field block template
		 * @var string
		 */
		static $default_field_block_template = '<span>*label*</span><span>*field*</span><span>*error*</span><span>*comment*</span>';
		
		
		/* COMMON FUNCTIONS */
		
		/**
		 * Gets attributes string 
		 * 
		 * @param string|array $attributes tag attributes in string or $name=>$value format
		 * @return string
		 */
		private static function GetAttributesString($attributes)
		{
			//checks whether the array was passed
			if (is_array($attributes)) 
			{
				$attributes_string = '';
				foreach ($attributes as $name => $value)
				{
					$attributes_string .= " $name = '$value'";
				}
				
				return $attributes_string;
			}
			else
			{
				return $attributes;
			}
		}
		
		/**
		 * Generates HTML tag without attributes parsing
		 * 
		 * @param $tag tag name
		 * @param string $attributes tag attributes
		 * @param $value tag value
		 */
		private static function TagRaw($tag, $attributes, $value = '')
		{
			echo "<$tag $attributes>$value</$tag>";
		}

		/**
		 * Gets HTML tag without attributes parsing
		 * 
		 * @param $tag tag name
		 * @param string $attributes tag attributes
		 * @param $value tag value
		 * 
		 * @return string
		 */
		private static function GetTagRaw($tag, $attributes, $value = '')
		{
			return "<$tag $attributes>$value</$tag>";
		}
		
		/**
		 * Generates HTML tag
		 * 
		 * @param $tag tag name
		 * @param string|array $attributes tag attributes
		 * @param $value tag value
		 */
		public static function Tag($tag, $attributes, $value = '')
		{
			$attributes = self::GetAttributesString($attributes);
			
			self::TagRaw($tag, $attributes, $value);
		}
		
		/**
		 * Gets HTML tag
		 * 
		 * @param $tag tag name
		 * @param string|array $attributes tag attributes
		 * @param $value tag value
		 * 
		 * @return string
		 */
		public static function GetTag($tag, $attributes, $value = '')
		{
			$attributes = self::GetAttributesString($attributes);
			
			return self::GetTagRaw($tag, $attributes, $value);
		}
		
		
		/* META TAGS */
		
		/**
		 * Generates 'meta' tag
		 * 
		 * @param string $name parameter name ('name' or 'http-equiv')
		 * @param string $value parameter value
		 * @param string $content the content of the meta information
		 * @param string|array $attributes tag attributes
		 */
		public static function Meta($name, $value, $content, $attributes = '')
		{
			$attributes = "content = '$content' $name = '$value' ".self::GetAttributesString($attributes);
			
			self::TagRaw('meta', $attributes);
		}
		
		/**
		 * Generates 'title' tag
		 * 
		 * @param string $value text to be displayed
		 * @param string|array $attributes tag attributes
		 */
		public static function Title($value, $attributes = '')
		{
			self::Tag('title', $attributes, $value);	
		}
		
		/**
		 * Generates 'link' tag
		 * 
		 * @param string|array $attributes tag attributes
		 */
		public static function Link($attributes)
		{
			self::Tag('link', $attributes);
		}

		/**
		 * Generates 'style' tag
		 * 
		 * @param string|array $attributes tag attributes
		 */
		public static function Style($value, $attributes = '')
		{
			self::Tag('style', $attributes, $value);
		}
		
		/**
		 * Includes CSS file by generating appropriate link tag
		 * @param $path_to_file path to the CSS file
		 */
		public static function IncludeCSSFile($path_to_file)
		{
			self::Link(array('type' => 'text/css', 'rel' => 'stylesheet', 'href' => $path_to_file));
		}
		
		/**
		 * Includes JavaScript file by generating appropriate script tag
		 * 
		 * @param $path_to_file path to the JavaScript file
		 */
		public static function IncludeJavaScriptFile($path_to_file)
		{
			self::Script('text/javascript', '', array('src' => $path_to_file));
		}

		
		/* TAG BUFFER*/
		
		/**
		 * Includes meta tags into  temporary buffer for to display
		 * 
		 * @param string $name parameter name ('name' or 'http-equiv')
		 * @param string $value parameter value
		 * @param string $content the content of the meta information
		 * @param string|array $attributes tag attributes
		 */
		public static function MetaBuffer($name, $value, $content, $attributes = '')
		{
			$attributes = "content = '$content' $name = '$value' ".self::GetAttributesString($attributes);
			$value = "<meta $attributes></meta>";
			
			
			if (!in_array($value, self::$meta_tag_buffer))
			{
				self::$meta_tag_buffer[] = $value;
			}
		}
		
		/**
		 * Display parsed content of $meta_tag_buffer array
		 */
		public static function DisplayMetaBuffer()
		{
			foreach (self::$meta_tag_buffer as $value)
			{
				echo $value;
			}
		}
		
		/**
		* Includes css tags into temporary buffer for to display
		* 
		* @param $path_to_file path to the CSS file
		*/
		public static function CSSBuffer($path_to_file)
		{
			$value = '<link type="text/css" rel="stylesheet" href="'.$path_to_file.'.css">';
			if (!in_array($value, self::$css_tag_buffer))
			{
				self::$css_tag_buffer[] = $value;
			} 
		}
		
		/**
		 * Display parsed content of $css_tag_buffer array
		 */
		public static function DisplayCSSBuffer()
		{
			foreach (self::$css_tag_buffer as $value)
			{
				echo $value;
			}
		}
		
		/**
		* Includes js tags into temporary buffer for to display
		* 
		* @param $path_to_file path to the js file
		*/
		public static function JSBuffer($path_to_file)
		{
			$value = "<script type='text/javascript' src='".$path_to_file.".js'></script>";
			if (!in_array($value, self::$js_tag_buffer))
			{
				self::$js_tag_buffer[] = $value;
			}
		}
		
		/**
		 * Display parsed content of $js_tag_buffer array
		 */
		public static function DisplayJSBuffer()
		{
			foreach (self::$js_tag_buffer as $value)
			{
				echo $value;
			}
		}
		
		
		/* GENERAL TAGS */
		
		/**
		 * Generates 'img' tag
		 * 
		 * @param string $src path to image (src HTML arrtibute value)
		 * @param string $alt alternative text
		 * @param string|array $attributes tag attributes
		 */
		public static function Img($src, $alt = '', $attributes = '')
		{
			Debugger::Log("img func", "start");	
			$attributes = "src = '$src' alt = '$alt' ".self::GetAttributesString($attributes);
			self::TagRaw('img', $attributes);
			Debugger::Log("img func", "end");
		}
		
		/**
		 * Generates 'a' tag
		 * 
		 * @param string|boolean $url url (href attribute) or false in no href tag needed
		 * @param string $content text or other content to be displayed
		 * @param string|array $attributes tag attributes
		 * @return unknown_type
		 */
		public static function Anchor($url = '', $content = '', $attributes = '')
		{
			$attributes = ($url === false) ? self::GetAttributesString($attributes) : "href = '$url' ".self::GetAttributesString($attributes);
			self::TagRaw('a', $attributes, $content);
		}
		
		
		/* FORM TAGS */
		
	    /**
		 * Generates a open form tag
		 *
		 * @param string $action form action 
		 * @param string $method data transmission method (GET/POST)
		 * @param string $attributes tag attributes
		 * @param boolean $is_start_tag defines whether to generate only the start form tag
		 */		
		public static function Form($action, $method = 'POST', $attributes = '', $is_start_tag = true)
		{
			$attributes = "action = '$action' method = '$method' ".self::GetAttributesString($attributes);
			
			//defines whether to generate only start form tag
			if ($is_start_tag)
			{
				echo "<form $attributes>";
			}
			else
			{
				self::Tag('form', $attributes);
			}
		}
		
		/**
		 * Generates 'input' tag
		 * 
		 * @param string $name input field name
		 * @param mixed $value input field value
		 * @param string $type input field type
		 * @param string|array $attributes tag attributes
		 */
		public static function Input($name, $value = '', $type = 'text', $attributes = '')
		{
			$attributes = "name = '$name' value = '$value' type = '$type' ".self::GetAttributesString($attributes);

			self::TagRaw('input', $attributes);
		}
		
		/**
		 * Generates 'input' tag with the 'text' type
		 * 
		 * @param string $name input field name
		 * @param mixed $value input field value
		 * @param string|array $attributes tag attributes
		 */
		public static function InputText($name = '', $value = '', $attributes = '') 
		{
			self::Input($name, $value, 'text', $attributes);
		}
		
		/**
		 * Generates 'input' tag with the 'hidden' type
		 * 
		 * @param string $name input field name
		 * @param mixed $value input field value
		 * @param string|array $attributes tag attributes
		 */
		public static function InputHidden($name = '', $value = '', $attributes = '') 
		{
			self::Input($name, $value, 'hidden', $attributes);
		}
		
		/**
		 * Generates 'input' tag with the 'password' type
		 * 
		 * @param string $name input field name
		 * @param mixed $value input field value
		 * @param string|array $attributes tag attributes
		 */
		public static function InputPassword($name = '', $value = '', $attributes = '') 
		{
			self::Input($name, $value, 'password', $attributes);
		}
		
		/**
		 * Generates 'input' tag with the 'radio' type
		 * 
		 * @param string $name input field name
		 * @param mixed $value input field value
		 * @param boolean|integer $is_checked defines whether the radio button is checked
		 * @param string|array $attributes tag attributes
		 */
		public static function InputRadio($name = '', $value = '', $is_checked = false, $attributes = '') 
		{
			$attributes = ($is_checked) ? " checked = 'checked' ".self::GetAttributesString($attributes) : $attributes;

			self::Input($name, $value, 'radio', $attributes);
		}
				
		/**
		 * Generates 'input' tag with the 'checkbox' type
		 * 
		 * @param string $name input field name
		 * @param mixed $value input field value
		 * @param boolean|integer $is_checked defines whether the checkbox is checked
		 * @param string|array $attributes tag attributes
		 */
		public static function InputCheckbox($name = '', $value = '', $is_checked = false, $attributes = '') 
		{
			$attributes = ($is_checked) ? " checked = 'checked' ".self::GetAttributesString($attributes) : $attributes;

			self::Input($name, $value, 'checkbox', $attributes);
		}
				
		/**
		 * Generates 'input' tag with the 'button' type
		 * 
		 * @param string $name input field name
		 * @param mixed $value input field value
		 * @param string|array $attributes tag attributes
		 */
		public static function InputButton($name = '', $value = '', $attributes = '') 
		{
			self::Input($name, $value, 'button', $attributes);
		}

		/**
		 * Generates 'input' tag with the 'submit' type
		 * 
		 * @param string $name input field name
		 * @param mixed $value input field value
		 * @param string|array $attributes tag attributes
		 */
		public static function InputSubmit($name = '', $value = '', $attributes = '') 
		{
			self::Input($name, $value, 'submit', $attributes);
		}
		
		/**
		 * Generates 'input' tag with the 'reset' type
		 * 
		 * @param string $name input field name
		 * @param mixed $value input field value
		 * @param string|array $attributes tag attributes
		 */
		public static function InputReset($name = '', $value = '', $attributes = '') 
		{
			self::Input($name, $value, 'reset', $attributes);
		}
		
		//TODO: to be done
		public static function InputFile() {}
		public static function InputImage() {}
		
		/**
		 * Generates 'select' tag with options
		 * 
		 * @param string $name select name
		 * @param array $options options array in the following format: array('0' => array('some_id' => 'value1', 'some_attributes'=>"disabled = 'disabled'", 'name'=>'text1'), '1' => array('some_id' => 'value2', 'some_name'=>'text2'))
		 * @param string $selected_value selected value
		 * @param string|boolean $empty_option empty option text or false
		 * @param string|array $attributes tag attributes
		 */
		public static function Select($name, array $options = array(), $selected_value = '', $empty_option = '-', $attributes = '') 
		{
			$attributes = "name = '$name' ".self::GetAttributesString($attributes);			
			
			$options_string = ($empty_option === false) ? "" : "<option value = ''>$empty_option</option>";
			
			//loops through options
			foreach ($options as $option)
			{
				$value = array_shift($option);
				$text = array_shift($option);
				$option_attributes = array_shift($option);
				
				//defines if the option is selected
				$selected = ($value == $selected_value) ? " selected = 'selected' " : "";
				
				//all options string
				$options_string .= "<option value = '$value' $selected $option_attributes>$text</option>";
			}
			
			self::TagRaw('select', $attributes, $options_string);
			
			echo "</select>";
		}
				
		/**
		 * Generates 'textarea' tag
		 * 
		 * @param string $name textarea name
		 * @param mixed $value textarea value
		 * @param string|array $attributes tag attributes
		 */
		public static function Textarea($name, $value = '', $attributes = '')
		{
			$attributes = "name = '$name' ".self::GetAttributesString($attributes);

			self::TagRaw('textarea', $attributes, $value);
		}

		/**
		 * Generates 'label' tag
		 * 
		 * @param $element_id value of the 'id' attribute
		 * @param $content label
		 * @param $attributes tag attributes
		 * 
		 * @return string
		 */
		public static function GetLabel($element_id, $content, $attributes = '')
		{
			$attributes = "for = '$element_id' ".self::GetAttributesString($attributes);
			
			return self::GetTagRaw('label', $attributes, $content);
		}
		
		//TODO: to finish
		public static function FormObject($action, $elements, $attributes = '', $template = array())
		{
			//form attributes string
			$attributes = "action = '$action' ".self::GetAttributesString($attributes);
			
			$content = $template['header'];
			
			foreach ($elements as $element)
			{
				//element id
				$element_id = (empty($element['attributes']['id'])) ? $element['name'] : $element['attributes']['id'];
				
				//element attributes
				$element_attributes = "name = '{$element['name']}' value = '{$element['value']}' type = '{$element['type']}' id = '$element_id' ".self::GetAttributesString($element['attributes']);
				
				//template
				$element_template = (empty($element['template'])) ? $template['element'] : $element['template'];	
				
				//adds the current element to the form content
				if (!empty($element_template))
				{
					//parses the template
					$element_content = str_replace('*label*', self::GetLabel($element_id, $element['label']), $element_template);
					$element_content = str_replace('*field*', self::GetTag($element['tag'], $element_attributes), $element_content);
					
					$content .= $element_content;
				}
				else
				{
					$content .= self::GetLabel($element_id, $element['label']).self::GetTag($element['tag'], $element_attributes);
				}
			}
			
			$content .= $template['footer'];
			
			self::TagRaw('form', $attributes, $content);
		}
		
		
		/* FORM BLOCKS */
		
		/**
		 * Displays input text field with label and other features
		 * 
		 * @param $name
		 * @param $value
		 * @param $label
		 * @param $settings
		 * @param $template
		 * @return unknown_type
		 */
		public static function InputTextBlock($name, $value, $label = '', $settings = array(), $template = '')
		{
			//input attributes
			$field_attributes = (empty($settings['field_attributes'])) ? '' : $settings['field_attributes'];
			$field_attributes = "name = '".$name."' value = '".$value."' type = 'text' ".self::GetAttributesString($field_attributes);
			
			$html_block = self::GetCommonInputFieldBlock($name, $value, $label, $settings, $template, self::$default_field_block_template);
			
			//inserts field into template
			$html_block = str_replace('*field*', self::GetTagRaw('input', $field_attributes), $html_block);
			
			//displays the block
			echo $html_block;
		}

		/**
		 * Displays input password field with label and other features
		 * 
		 * @param $name
		 * @param $value
		 * @param $label
		 * @param $settings
		 * @param $template
		 * @return unknown_type
		 */
		public static function InputPasswordBlock($name, $value, $label = '', $settings = array(), $template = '')
		{
			//input attributes
			$field_attributes = (empty($settings['field_attributes'])) ? '' : $settings['field_attributes'];
			$field_attributes = "name = '".$name."' value = '".$value."' type = 'password' ".self::GetAttributesString($field_attributes);
			
			$html_block = self::GetCommonInputFieldBlock($name, $value, $label, $settings, $template, self::$default_field_block_template);
			
			//inserts field into template
			$html_block = str_replace('*field*', self::GetTagRaw('input', $field_attributes), $html_block);
			
			//displays the block
			echo $html_block;
		}		
		
		/**
		 * Displays input text field with label and other features
		 * 
		 * @param $name
		 * @param $value
		 * @param $label
		 * @param $settings
		 * @param $template
		 * @return unknown_type
		 */
		public static function TextareaBlock($name, $value, $label = '', $settings = array(), $template = '')
		{
			//input attributes
			$field_attributes = (empty($settings['field_attributes'])) ? '' : $settings['field_attributes'];
			$field_attributes = "name = '".$name."' ".self::GetAttributesString($field_attributes);
			
			$html_block = self::GetCommonInputFieldBlock($name, $value, $label, $settings, $template, self::$default_field_block_template);
			
			//inserts field into template
			$html_block = str_replace('*field*', self::GetTagRaw('textarea', $field_attributes, $value), $html_block);
			
			//displays the block
			echo $html_block;			
		}		
		
		/**
		 * Displays select box field with label and other features
		 * 
		 * @param array $name
		 * @param $options
		 * @param $value
		 * @param $label
		 * @param $settings
		 * @param $template
		 * @return unknown_type
		 */
		public static function SelectBlock($name, array $options = array(), $value = '', $label = '', $settings = array(), $template = '')
		{
			//input attributes
			$field_attributes = (empty($settings['field_attributes'])) ? '' : $settings['field_attributes'];
			$field_attributes = "name = '".$name."' ".self::GetAttributesString($field_attributes);
			
			//empty option for the select box
			$settings['field_empty_option'] = (!isset($settings['field_empty_option'])) ? '-' : $settings['field_empty_option'];
			
			$html_block = self::GetCommonInputFieldBlock($name, $value, $label, $settings, $template, self::$default_field_block_template);
			
			//gets the select tag contents
			ob_start();
			self::Select($name, $options, $value, $settings['field_empty_option'], $field_attributes);
			$field = ob_get_contents();
			ob_end_clean();
			
			//inserts field into template
			$html_block = str_replace('*field*', $field, $html_block);
			
			//displays the block
			echo $html_block;
		}
		
		/**
		 * Displays submit button within template
		 * 
		 * @param $name
		 * @param $value
		 * @param $settings
		 * @param $template
		 * @return unknown_type
		 */
		public static function InputSubmitBlock($name, $value, $settings = array(), $template = '')
		{
			//default template
			$default_template = '<span>*field*</span>';
			
			//input attributes
			$field_attributes = (empty($settings['field_attributes'])) ? '' : $settings['field_attributes'];
			$field_attributes = "name = '".$name."' value = '".$value."' type = 'submit' ".self::GetAttributesString($field_attributes);
			
			$html_block = self::GetCommonInputFieldBlock($name, $value, '', $settings, $template, $default_template);
			
			//inserts field into template
			$html_block = str_replace('*field*', self::GetTagRaw('input', $field_attributes), $html_block);
			
			//displays the block
			echo $html_block;			
		}
		
		/**
		 * Gets the common HTML output for the input field blocks
		 * 
		 * @param $name
		 * @param $value
		 * @param $label
		 * @param $settings
		 * @param $template
		 * @param $default_template
		 * @return unknown_type
		 */
		private static function GetCommonInputFieldBlock($name, $value, $label, $settings = array(), $template, $default_template)
		{			
			//input error
			$input_error = (empty($settings['field_error'])) ? '' : $settings['field_error'];
			
			//input comment
			$input_comment = (empty($settings['field_comment'])) ? '' : $settings['field_comment'];
			
			//label attributes
			$label_attributes = (empty($settings['label_attributes'])) ? '' : $settings['label_attributes'];
			
			//xhtml template
			$template = (empty($template)) ? $default_template : $template;
			
			//inserts label into template
			$html_block = str_replace('*label*', self::GetLabel($name, $label, $label_attributes), $template);
			
			//inserts input error into template
			$html_block = str_replace('*error*', $input_error, $html_block);

			//inserts input error into template
			$html_block = str_replace('*comment*', $input_comment, $html_block);
			
			return $html_block;
		}

		/**
		 * Displays input checkbox field with label and other features
		 * 
		 * @param $name
		 * @param $value
		 * @param $label
		 * @param $settings
		 * @param $template
		 * @return unknown_type
		 */
		public static function InputCheckboxBlock($name, $is_checked, $label = '', $value, $settings = array(), $template = '')
		{
			//input attributes
			$field_attributes = (empty($settings['field_attributes'])) ? '' : $settings['field_attributes'];
			$checked_attribute = ($is_checked) ? "checked = 'checked'" : "";
			$field_attributes = "name = '".$name."' value = '".$value."' type = 'checkbox' $checked_attribute ".self::GetAttributesString($field_attributes);
			
			$html_block = self::GetCommonInputFieldBlock($name, $value, $label, $settings, $template, self::$default_field_block_template);
			
			//inserts field into template
			$html_block = str_replace('*field*', self::GetTagRaw('input', $field_attributes), $html_block);
			
			//displays the block
			echo $html_block;
		}
		
		
		/* JAVASCRIPT */
		
		/**
		 * Generates 'script' tag
		 * 
		 * @param string $type script type
		 * @param string $value script to be executed
		 * @param string|array $attributes tag attributes
		 */
		public static function Script($type, $value, $attributes = '')
		{
			$attributes = "type = '$type' ".self::GetAttributesString($attributes);
			
			self::TagRaw('script', $attributes, $value);
		}
		
		//TODO: to be removed to another helper
		private static function Alert() {}
	}
?>